/*
 * @Author: Swance
 * @Date: 2023-12-30
 * @Description: 图形插件
 */
import { fabric } from 'fabric';
import { IEditor, Shape } from '@/types/global';
import { v4 as uuid } from 'uuid';
import { BoardSyncEvent, JsonOption } from '@/utils/Const.ts';

class ShapePlugin {
  canvas: fabric.Canvas;
  editor: IEditor;
  static pluginName = 'ShapePlugin';
  static apis: string[] = [
    'addRect',
    'addRoundRect',
    'addCircle',
    'addEllipse',
    'addTriangle',
    'setShapeFillColor',
    'setShapeBorderColor',
    'setShapeBorderThickness',
    'setShapeBorderStyle',
  ];

  constructor(canvas: fabric.Canvas, editor: IEditor) {
    this.canvas = canvas;
    this.editor = editor;
  }

  // 添加矩形图形
  addRect() {
    const rect = new fabric.Rect({
      top: 100, // 距离容器顶部 100px
      left: 100, // 距离容器左侧 100px
      width: 100, // 宽度 100px
      height: 100, // 高度 100px
      stroke: 'rgba(0, 0, 0, 1)', // 边框颜色
      strokeWidth: 2, // 边框粗细：5px
      fill: 'transparent', // 填充色
      strokeUniform: true,
      erasable: false, // 不允许擦拭
      lock: false,
      id: uuid(),
    });
    this.canvas.add(rect);
    this.canvas.renderAll();
    // this.canvas.setActiveObject(rect);
    this.editor.emit(BoardSyncEvent.ADD, {
      isNewAction: true,
      newElements: [rect],
    });
  }

  // 添加圆角矩形
  addRoundRect() {
    const rect = new fabric.Rect({
      top: 100, // 距离容器顶部 100px
      left: 100, // 距离容器左侧 100px
      width: 120, // 宽度 100px
      height: 100, // 高度 100px
      rx: 20, // x轴的半径
      ry: 20, // y轴的半径
      stroke: 'rgba(0, 0, 0, 1)', // 边框颜色
      strokeWidth: 2, // 边框粗细：5px
      fill: 'transparent', // 填充色
      strokeUniform: true,
      erasable: false, // 不允许擦拭
      lock: false,
      id: uuid(),
    });
    this.canvas.add(rect);
    this.canvas.renderAll();
    // this.canvas.setActiveObject(rect);
    this.editor.emit(BoardSyncEvent.ADD, {
      isNewAction: true,
      newElements: [rect],
    });
  }

  // 添加圆形
  addCircle() {
    const circle = new fabric.Circle({
      top: 100,
      left: 100,
      radius: 50, // 圆的半径 50
      stroke: 'rgba(0, 0, 0, 1)', // 边框颜色
      strokeWidth: 2, // 边框粗细：5px
      fill: 'transparent', // 填充色
      strokeUniform: true,
      erasable: false, // 不允许擦拭
      lock: false,
      id: uuid(),
    });
    this.canvas.add(circle);
    this.canvas.renderAll();
    // this.canvas.setActiveObject(circle);
    this.editor.emit(BoardSyncEvent.ADD, {
      isNewAction: true,
      newElements: [circle],
    });
  }

  // 添加椭圆
  addEllipse() {
    const ellipse = new fabric.Ellipse({
      top: 100,
      left: 100,
      rx: 70,
      ry: 30,
      stroke: 'rgba(0, 0, 0, 1)', // 边框颜色
      strokeWidth: 2, // 边框粗细：5px
      fill: 'transparent', // 填充色
      strokeUniform: true,
      erasable: false, // 不允许擦拭
      lock: false,
      id: uuid(),
    });
    this.canvas.add(ellipse);
    this.canvas.renderAll();
    // this.canvas.setActiveObject(ellipse);
    this.editor.emit(BoardSyncEvent.ADD, {
      isNewAction: true,
      newElements: [ellipse],
    });
  }

  // 添加三角形
  addTriangle() {
    const triangle = new fabric.Triangle({
      top: 100,
      left: 100,
      width: 100, // 底边长度
      height: 100, // 底边到对角的距离
      stroke: 'rgba(0, 0, 0, 1)', // 边框颜色
      strokeWidth: 2, // 边框粗细：5px
      fill: 'transparent', // 填充色
      strokeUniform: true,
      erasable: false, // 不允许擦拭
      lock: false,
      id: uuid(),
    });
    this.canvas.add(triangle);
    this.canvas.renderAll();
    // this.canvas.setActiveObject(triangle);
    this.editor.emit(BoardSyncEvent.ADD, {
      isNewAction: true,
      newElements: [triangle],
    });
  }

  getActiveShapeObject() {
    const activeObject = this.canvas.getActiveObject();
    if (
      activeObject &&
      (activeObject.type === 'rect' ||
        activeObject.type === 'triangle' ||
        activeObject.type === 'circle' ||
        activeObject.type === 'ellipse')
    ) {
      return activeObject;
    }
    return null;
  }

  // 修改图形填充色
  setShapeFillColor(color: string) {
    const shape = this.getActiveShapeObject();
    if (!shape) return;
    const oldElementJson = shape.toJSON(JsonOption);
    shape.fill = color;
    shape.dirty = true;
    const newElementJson = shape.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 修改图形边框颜色
  setShapeBorderColor(color: string) {
    const shape = this.getActiveShapeObject();
    if (!shape) return;
    const oldElementJson = shape.toJSON(JsonOption);
    shape.stroke = color;
    shape.dirty = true;
    const newElementJson = shape.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 修改图形边框粗细
  setShapeBorderThickness(width: number) {
    const shape = this.getActiveShapeObject();
    if (!shape) return;
    const oldElementJson = shape.toJSON(JsonOption);
    shape.strokeWidth = width;
    shape.dirty = true;
    const newElementJson = shape.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }

  // 修改图形边框样式
  setShapeBorderStyle(style: string) {
    const shape = this.getActiveShapeObject();
    if (!shape) return;
    const oldElementJson = shape.toJSON(JsonOption);
    switch (style) {
      case 'line':
        shape.strokeDashArray = undefined;
        break;
      case 'dash':
        shape.strokeDashArray = [5, 5];
        break;
      case 'smallDash':
        shape.strokeDashArray = [2, 2];
        break;
    }
    shape.dirty = true;
    const newElementJson = shape.toJSON(JsonOption);
    this.editor.emit(BoardSyncEvent.UPDATE, {
      isNewAction: true,
      oldElements: [oldElementJson],
      newElements: [newElementJson],
    });
    this.canvas.requestRenderAll();
  }
}
export default ShapePlugin;
